﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChessSuite.Utilities.Common.Enumeations;

namespace ChessSuite.Utilities.Common.Utilities
{
    public static partial class PieceTypeUtility
    {
        #region Enumeration over single and multipieces.
        public static IEnumerable<PieceType> IndividualPieces(this PieceType piece)
        {
            if (piece.HasKing()) yield return PieceType.King;
            if (piece.HasQueen()) yield return PieceType.Queen;
            if (piece.HasRook()) yield return PieceType.Rook;
            if (piece.HasKnight()) yield return PieceType.Knight;
            if (piece.HasBishop()) yield return PieceType.Bishop;
            if (piece.HasPawn()) yield return PieceType.Pawn;
        }

        public static IEnumerable<PieceType> IndividualPieces(this IEnumerable<PieceType> piece)
        {
            foreach (PieceType p in piece) if (p.HasKing()) yield return PieceType.King;
            foreach (PieceType p in piece) if (p.HasQueen()) yield return PieceType.Queen;
            foreach (PieceType p in piece) if (p.HasRook()) yield return PieceType.Rook;
            foreach (PieceType p in piece) if (p.HasKnight()) yield return PieceType.Knight;
            foreach (PieceType p in piece) if (p.HasBishop()) yield return PieceType.Bishop;
            foreach (PieceType p in piece) if (p.HasPawn()) yield return PieceType.Pawn;
        }
        #endregion

        public static int NumberOfIndividualPieces(this PieceType piece)
        {
            return piece.IndividualPieces().Count();
        }

        public static int NumberOfIndividualPieces(this IEnumerable<PieceType> piece)
        {
            return piece.IndividualPieces().Count();
        }

        public static int Count(this PieceType piece, PieceType value)
        {
            //Debug.Assert(value.IsBasicPiece());
            if (!value.IsBasicPiece())
                throw new ArgumentException("Only basic (Pawn, Bishop, Knight, Rook, Queen or King) allowed for comparison.",
                    "value");
            return piece.IndividualPieces().Count(p => p.IsPiece(value));
        }

        public static int Count(this IEnumerable<PieceType> piece, PieceType value)
        {
            //Debug.Assert(value.IsBasicPiece());
            if (!value.IsBasicPiece())
                throw new ArgumentException("Only basic (Pawn, Bishop, Knight, Rook, Queen or King) allowed for comparison.",
                    "value");
            return piece.IndividualPieces().Count(p => p.IsPiece(value));
        }

        public static IEnumerable<PieceType> FromIndividualCounts(int pawns, int bishops, int knights,
            int rooks, int queens, int kings)
        {
            //Debug.Assert(pawns >= 0);
            if (pawns < 0)
                throw new ArgumentException(String.Format("Invalid number of pawns \"{0}\".", pawns), "pawns");
            //Debug.Assert(bishops >= 0);
            if (bishops < 0)
                throw new ArgumentException(String.Format("Invalid number of bishops \"{0}\".", bishops), "bishops");
            //Debug.Assert(knights >= 0);
            if (knights < 0)
                throw new ArgumentException(String.Format("Invalid number of knights \"{0}\".", knights), "knights");
            //Debug.Assert(rooks >= 0);
            if (rooks < 0)
                throw new ArgumentException(String.Format("Invalid number of rooks \"{0}\".", rooks), "rooks");
            //Debug.Assert(queens >= 0);
            if (queens < 0)
                throw new ArgumentException(String.Format("Invalid number of queens \"{0}\".", queens), "queens");
            //Debug.Assert(kings >= 0 && kings < 2);
            if (kings < 0 || kings > 1)
                throw new ArgumentException(String.Format("Invalid number of kings \"{0}\".", kings), "kings");

            while (pawns > 0 || bishops > 0 || knights > 0 ||
                rooks > 0 || queens > 0 || kings > 0)
            {
                PieceType res = PieceType.None;
                if (pawns > 0) { res |= PieceType.Pawn; pawns--; } // Could've -- pawn in if-clause, but could theoretically have been unpleasant.
                if (bishops > 0) { res |= PieceType.Bishop; bishops--; }
                if (knights > 0) { res |= PieceType.Knight; knights--; }
                if (rooks > 0) { res |= PieceType.Rook; rooks--; }
                if (queens > 0) { res |= PieceType.Queen; queens--; }
                if (kings > 0) { res |= PieceType.King; kings--; }
                yield return res;
            }
        }
    }
}
